package config

import (
	"fmt"
	"gopkg.in/yaml.v3"
	"gorm.io/driver/mysql"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"smart-weekly-report/models"
	"time"
)

// Config holds application configuration
type Config struct {
	GitRepoPath   string `yaml:"git_repo_path"`
	FeishuWebhook string `yaml:"feishu_webhook"`
	FeishuKey     string `yaml:"feishu_key"`
	GenkitAPIKey  string `yaml:"genkit_api_key"`
	ZhipuAPIKey   string `yaml:"zhipu_api_key"`
	// Database configuration
	DB struct {
		Driver          string `yaml:"driver"`
		Path            string `yaml:"path"`
		Host            string `yaml:"host"`
		Port            int    `yaml:"port"`
		Username        string `yaml:"username"`
		Password        string `yaml:"password"`
		DBName          string `yaml:"db_name"`
		MaxIdleConns    int    `yaml:"max_idle_conns"`
		MaxOpenConns    int    `yaml:"max_open_conns"`
		ConnMaxLifetime int    `yaml:"conn_max_lifetime"` // 单位：分钟
		LogMode         bool   `yaml:"log_mode"`
	} `yaml:"database"`
}

var AppConfig Config
var Db *gorm.DB

// LoadConfig loads configuration from YAML file with environment variable fallback
func LoadConfig() {
	// Initialize default values
	AppConfig = Config{
		DB: struct {
			Driver          string `yaml:"driver"`
			Path            string `yaml:"path"`
			Host            string `yaml:"host"`
			Port            int    `yaml:"port"`
			Username        string `yaml:"username"`
			Password        string `yaml:"password"`
			DBName          string `yaml:"db_name"`
			MaxIdleConns    int    `yaml:"max_idle_conns"`
			MaxOpenConns    int    `yaml:"max_open_conns"`
			ConnMaxLifetime int    `yaml:"conn_max_lifetime"`
			LogMode         bool   `yaml:"log_mode"`
		}(struct {
			Driver          string
			Path            string
			Host            string
			Port            int
			Username        string
			Password        string
			DBName          string
			MaxIdleConns    int
			MaxOpenConns    int
			ConnMaxLifetime int
			LogMode         bool
		}{"mysql", "weekly_report.db", "localhost", 3306, "root", "password", "weekly_report", 10, 100, 60, false}),
	}

	// Get config file path
	configPath := getConfigPath()

	// Try to load from config file if exists
	if _, err := os.Stat(configPath); err == nil {
		content, err := ioutil.ReadFile(configPath)
		if err != nil {
			log.Printf("Failed to read config file: %v", err)
		} else {
			if err := yaml.Unmarshal(content, &AppConfig); err != nil {
				log.Printf("Failed to parse YAML config: %v", err)
			} else {
				log.Println("Config loaded from", configPath)
			}
		}
	}

	// Load from environment variables as fallback
	loadFromEnv()

	// Validate configuration
	validateConfig()
}

// getConfigPath returns the path to the configuration file
func getConfigPath() string {
	// First try current directory
	currentDir, err := os.Getwd()
	if err != nil {
		log.Printf("Failed to get current directory: %v", err)
		return "config.yaml"
	}

	// Check common config file locations
	configPaths := []string{
		filepath.Join(currentDir, "config.yaml"),
		filepath.Join(currentDir, "config", "config.yaml"),
		"/etc/week_report/config.yaml",
	}

	// Return the first existing config file
	for _, path := range configPaths {
		if _, err := os.Stat(path); err == nil {
			return path
		}
	}

	// Default to config.yaml in current directory
	return filepath.Join(currentDir, "config.yaml")
}

// loadFromEnv loads configuration from environment variables
func loadFromEnv() {
	if gitRepoPath := os.Getenv("GIT_REPO_PATH"); gitRepoPath != "" {
		AppConfig.GitRepoPath = gitRepoPath
	}

	if feishuWebhook := os.Getenv("FEISHU_WEBHOOK"); feishuWebhook != "" {
		AppConfig.FeishuWebhook = feishuWebhook
	}
	// 飞书 Key
	if feishuKey := os.Getenv("FEISHU_KEY"); feishuKey != "" {
		AppConfig.FeishuKey = feishuKey
	}

	if genkitAPIKey := os.Getenv("GENKIT_API_KEY"); genkitAPIKey != "" {
		AppConfig.GenkitAPIKey = genkitAPIKey
	}

	// 智谱 API 密钥
	if zhipuAPIKey := os.Getenv("ZHIPU_API_KEY"); zhipuAPIKey != "" {
		AppConfig.ZhipuAPIKey = zhipuAPIKey
	}

	// Database environment variables
	if dbDriver := os.Getenv("DB_DRIVER"); dbDriver != "" {
		AppConfig.DB.Driver = dbDriver
	}

	if dbPath := os.Getenv("DB_PATH"); dbPath != "" {
		AppConfig.DB.Path = dbPath
	}

	if dbHost := os.Getenv("DB_HOST"); dbHost != "" {
		AppConfig.DB.Host = dbHost
	}

	// 增加数据库相关的环境变量加载
	if dbPort := os.Getenv("DB_PORT"); dbPort != "" {
		// 这里需要将字符串转换为整数，简化版本暂时省略
	}

	if dbUsername := os.Getenv("DB_USERNAME"); dbUsername != "" {
		AppConfig.DB.Username = dbUsername
	}

	if dbPassword := os.Getenv("DB_PASSWORD"); dbPassword != "" {
		AppConfig.DB.Password = dbPassword
	}

	if dbName := os.Getenv("DB_NAME"); dbName != "" {
		AppConfig.DB.DBName = dbName
	}
}

// validateConfig checks if required configuration values are set
func validateConfig() {
	// Check required fields
	if AppConfig.GitRepoPath == "" {
		log.Println("Warning: GIT_REPO_PATH is not set")
	}

	// 数据库配置验证
	if AppConfig.DB.Driver == "mysql" {
		if AppConfig.DB.Host == "" {
			log.Println("Warning: DB_HOST is not set for MySQL")
		}
		if AppConfig.DB.Port <= 0 {
			log.Println("Warning: DB_PORT is not set correctly for MySQL")
		}
		if AppConfig.DB.Username == "" {
			log.Println("Warning: DB_USERNAME is not set for MySQL")
		}
		if AppConfig.DB.DBName == "" {
			log.Println("Warning: DB_NAME is not set for MySQL")
		}
	}
}

// GetConfig returns the application configuration
func GetConfig() Config {
	return AppConfig
}

// InitDB initializes the database connection
func InitDB() {
	var err error
	var db *gorm.DB

	// 配置 GORM 日志级别
	logLevel := logger.Warn
	if AppConfig.DB.LogMode {
		logLevel = logger.Info
	}

	gormConfig := &gorm.Config{
		Logger: logger.Default.LogMode(logLevel),
	}

	// Choose database driver based on configuration
	switch AppConfig.DB.Driver {
	case "mysql":
		// MySQL 连接配置
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
			AppConfig.DB.Username,
			AppConfig.DB.Password,
			AppConfig.DB.Host,
			AppConfig.DB.Port,
			AppConfig.DB.DBName,
		)
		log.Printf("Connecting to MySQL database: %s:%d/%s", AppConfig.DB.Host, AppConfig.DB.Port, AppConfig.DB.DBName)
		db, err = gorm.Open(mysql.Open(dsn), gormConfig)
	case "sqlite":
		log.Printf("Connecting to SQLite database: %s", AppConfig.DB.Path)
		db, err = gorm.Open(sqlite.Open(AppConfig.DB.Path), gormConfig)
	default:
		// Default to SQLite if driver is not specified or unsupported
		log.Printf("Unknown database driver: %s, defaulting to SQLite", AppConfig.DB.Driver)
		db, err = gorm.Open(sqlite.Open(AppConfig.DB.Path), gormConfig)
	}

	if err != nil {
		log.Fatalf("Database connection failed: %v", err)
	}

	// 配置连接池
	sqlDB, err := db.DB()
	if err != nil {
		log.Fatalf("Failed to get database object: %v", err)
	}

	// SetMaxIdleConns 设置空闲连接池中连接的最大数量
	sqlDB.SetMaxIdleConns(AppConfig.DB.MaxIdleConns)

	// SetMaxOpenConns 设置打开数据库连接的最大数量
	sqlDB.SetMaxOpenConns(AppConfig.DB.MaxOpenConns)

	// SetConnMaxLifetime 设置连接可复用的最大时间（分钟转换为秒）
	sqlDB.SetConnMaxLifetime(time.Duration(AppConfig.DB.ConnMaxLifetime) * time.Minute)

	// 自动迁移
	err = db.AutoMigrate(&models.GitCommit{}, &models.WeeklyReport{})
	if err != nil {
		log.Printf("Database migration failed: %v", err)
	} else {
		log.Println("Database migration completed successfully")
	}

	Db = db
}
